package cn.gson.financial.kernel.service.impl;

import cn.gson.financial.kernel.common.DoubleValueUtil;
import cn.gson.financial.kernel.dao.ChronologicalAccountDao;
import cn.gson.financial.kernel.model.entity.AccountingCategoryDetails;
import cn.gson.financial.kernel.model.entity.Subject;
import cn.gson.financial.kernel.model.entity.VoucherDetails;
import cn.gson.financial.kernel.model.entity.VoucherDetailsAuxiliary;
import cn.gson.financial.kernel.model.mapper.AccountingCategoryDetailsMapper;
import cn.gson.financial.kernel.model.mapper.SubjectMapper;
import cn.gson.financial.kernel.model.mapper.VoucherDetailsAuxiliaryMapper;
import cn.gson.financial.kernel.model.mapper.VoucherDetailsMapper;
import cn.gson.financial.kernel.model.vo.CategoryVo;
import cn.gson.financial.kernel.model.vo.ChronologicalAccountVo;
import cn.gson.financial.kernel.model.vo.InitBlanceVo;
import cn.gson.financial.kernel.service.VoucherDetailsService;
import cn.gson.financial.kernel.utils.BaseUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class VoucherDetailsServiceImpl extends ServiceImpl<VoucherDetailsMapper, VoucherDetails> implements VoucherDetailsService {

    @Autowired
    private SubjectMapper subjectMapper;

    @Autowired
    private AccountingCategoryDetailsMapper categoryDetailsMapper;

    @Autowired
    private ChronologicalAccountDao chronologicalAccountDao;

    @Autowired
    private VoucherDetailsAuxiliaryMapper detailsAuxiliaryMapper;
    @Autowired
    private VoucherDetailsMapper voucherDetailsMapper;

    @Override
    public int batchInsert(List<VoucherDetails> list) {
        return baseMapper.batchInsert(list);
    }

    @Override
    public boolean save(VoucherDetails entity) {
        LambdaQueryWrapper<VoucherDetails> qw = Wrappers.lambdaQuery();
        qw.eq(VoucherDetails::getAccountSetsId, entity.getAccountSetsId());
        qw.eq(VoucherDetails::getSubjectId, entity.getSubjectId());
        qw.eq(VoucherDetails::getSubjectCode, entity.getSubjectCode());
        qw.isNull(VoucherDetails::getVoucherId);
        if (this.baseMapper.selectCount(qw) > 0) {
            return retBool(voucherDetailsMapper.updateVoucherDetails(entity));
        }
        return super.save(entity);
    }

    /**
     * 期初数据
     *
     * @param accountSetsId
     * @param type
     * @return
     */
    @Override
    public List<VoucherDetails> balanceList(Integer accountSetsId, String type,Integer currencyId) {
        return this.baseMapper.selectBalanceList(accountSetsId, type,currencyId);
    }

    /**
     * 期初试算平衡
     *
     * @param accountSetsId
     * @return
     */
    @Override
    public Map<String, Map<String, Double>> trialBalance(Integer accountSetsId) {
        Map<String, Double> beginningBalance = this.baseMapper.selectListInitialCheckData(accountSetsId);
        Double property = this.baseMapper.selectBassetsAndLiabilities(accountSetsId,"资产");
        Double liabilities = this.baseMapper.selectBassetsAndLiabilities(accountSetsId,"负债");
        Double equity = this.baseMapper.selectBassetsAndLiabilities(accountSetsId,"权益");
        Map<String, Double> bb = new HashMap<>();
        Map<String, Double> bl = new HashMap<>();
        bb.put("借", beginningBalance != null ? beginningBalance.get("debit_amount") : 0d);
        bb.put("贷", beginningBalance != null ? beginningBalance.get("credit_amount") : 0d);
        bl.put("资产",property);
        bl.put("权益",DoubleValueUtil.getNotNullVal(equity)+DoubleValueUtil.getNotNullVal(liabilities));

//        Map<String, List<Map>> collect = liabilities.stream().collect(Collectors.groupingBy(map -> (String) map.get("type")));
//        collect.forEach((type, maps) -> {
//            Optional<Map> borrow = maps.stream().filter(map -> "借".equals(map.get("balance_direction"))).findFirst();
//            Optional<Map> credit = maps.stream().filter(map -> "贷".equals(map.get("balance_direction"))).findFirst();
//
//            if (borrow.isPresent() && credit.isPresent()) {
//                Double balanceBorrow = DoubleValueUtil.getNotNullVal((Double) borrow.get().get("debit_amount"), (Double) borrow.get().get("credit_amount"));
//                Double balanceCredit = DoubleValueUtil.getNotNullVal((Double) credit.get().get("debit_amount"), (Double) credit.get().get("credit_amount"));
//                bl.put(type, balanceBorrow - balanceCredit);
//            } else if (borrow.isPresent()) {
//                Double balanceBorrow = DoubleValueUtil.getNotNullVal((Double) borrow.get().get("debit_amount"), (Double) borrow.get().get("credit_amount"));
//                bl.put(type, balanceBorrow);
//            } else if (credit.isPresent()) {
//                Double balanceCredit = DoubleValueUtil.getNotNullVal((Double) credit.get().get("debit_amount"), (Double) credit.get().get("credit_amount"));
//                bl.put(type, balanceCredit);
//            }
//        });

        Map<String, Map<String, Double>> data = new HashMap<>();

        data.put("beginningBalance", bb);
        data.put("liabilities", bl);

        return data;
    }

    @Override
    public void saveAuxiliary(Integer accountSetsId, HashMap<String, Object> entity) {
        Integer subjectId = (Integer) entity.get("subjectId");
        JSONObject auxiliary = (JSONObject) entity.get("auxiliary");
        Subject subject = subjectMapper.selectById(subjectId);
        List<AccountingCategoryDetails> categoryDetails = categoryDetailsMapper.selectBatchIds(auxiliary.values().stream().mapToInt(o -> (Integer) o).boxed().collect(Collectors.toList()));
        StringBuilder auxiliaryTitle = new StringBuilder();
        StringBuilder subjectCode = new StringBuilder(subject.getCode());
        for (AccountingCategoryDetails cd : categoryDetails) {
//            auxiliaryTitle.append("_").append(cd.getId()).append("_").append(cd.getName());
            auxiliaryTitle.append("_").append(cd.getName());
//            subjectCode.append("_").append(cd.getId());
            subjectCode.append("_").append(cd.getCode());
        }

        LambdaQueryWrapper<VoucherDetails> qw = Wrappers.lambdaQuery();
        qw.eq(VoucherDetails::getAccountSetsId, accountSetsId);
        qw.eq(VoucherDetails::getSubjectId, subjectId);
        qw.eq(VoucherDetails::getSubjectCode, subjectCode.toString());
        qw.isNull(VoucherDetails::getVoucherId);

        VoucherDetails details = this.baseMapper.selectOne(qw);
        if (details == null) {
            details = new VoucherDetails();
            details.setSummary("期初");
            details.setSubjectId(subjectId);
            details.setSubjectName(subjectCode.toString() + "-" + subject.getName());
            details.setSubjectCode(subjectCode.toString());
            details.setAuxiliaryTitle(auxiliaryTitle.toString());
            details.setAccountSetsId(accountSetsId);
            this.baseMapper.insert(details);
        }

        List<VoucherDetailsAuxiliary> voucherDetailsAuxiliaries = new ArrayList<>();

        for (AccountingCategoryDetails cd : categoryDetails) {
            LambdaQueryWrapper<VoucherDetailsAuxiliary> aqw = Wrappers.lambdaQuery();
            aqw.eq(VoucherDetailsAuxiliary::getVoucherDetailsId, details.getId());
            aqw.eq(VoucherDetailsAuxiliary::getAccountingCategoryId, cd.getAccountingCategoryId());
            aqw.eq(VoucherDetailsAuxiliary::getAccountingCategoryDetailsId, cd.getId());

            if (detailsAuxiliaryMapper.selectCount(aqw) == 0) {
                VoucherDetailsAuxiliary vda = new VoucherDetailsAuxiliary();
                vda.setVoucherDetailsId(details.getId());
                vda.setAccountingCategoryId(cd.getAccountingCategoryId());
                vda.setAccountingCategoryDetailsId(cd.getId());
                voucherDetailsAuxiliaries.add(vda);
            }
        }

        if (!voucherDetailsAuxiliaries.isEmpty()) {
            detailsAuxiliaryMapper.batchInsert(voucherDetailsAuxiliaries);
        }
    }

    @Override
    public List<VoucherDetails> auxiliaryList(Integer accountSetsId, String type, Integer currencyId) {
        return this.baseMapper.selectAuxiliaryList(accountSetsId, type,currencyId);
    }

    /**
     * 科目会计期间的累计金额
     *
     * @param accountSetsId
     * @param codeList
     * @param currentAccountDate
     * @return
     */
    @Override
    public Map<String, VoucherDetails> getAggregateAmount(Integer accountSetsId, Set<String> codeList, Date currentAccountDate) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(currentAccountDate);
        List<VoucherDetails> details = this.baseMapper.selectAggregateAmount(accountSetsId, codeList, instance.get(Calendar.YEAR), instance.get(Calendar.MONTH) + 1);
        return details.stream().collect(Collectors.toMap(VoucherDetails::getSubjectCode, voucherDetails -> voucherDetails));
    }

    @Override
    public List<ChronologicalAccountVo> selectChronologicalAccountByParam(Integer accsetsId,
                                                                          String sTime,
                                                                          String eTime,
                                                                          String wordCode,
                                                                          String word,
                                                                          String summary,
                                                                          String createMemberName,
                                                                          String subjectCode,
                                                                          String sMoney,
                                                                          String eMoney,
                                                                          Integer sort
    ) {
        String sSubjectCode="";
        String eSubjectCode="";
        String sWordCode = "";
        String eWordCode = "";

        List<String> wordCodeList = new ArrayList<>();
        List<String> subCodeList = new ArrayList<>();

        // 对 科目进行 判断
        if(BaseUtil.checkValueIsNull(subjectCode).contains("-")){
            String[] sry = subjectCode.split("-");
            sSubjectCode = sry[0];
            eSubjectCode = sry[1];
        }else if(BaseUtil.checkValueIsNull(subjectCode).contains(",")){
            String[] sry = subjectCode.split(",");
            subCodeList.add(sry[0]);
            subCodeList.add(sry[1]);
        }else {
            if(!BaseUtil.checkValueIsNull(subjectCode).equals("")){
                subCodeList.add(subjectCode);
            }
        }

        //对 凭证字号 判断
        if(BaseUtil.checkValueIsNull(wordCode).contains("-")){
            String[] sry = wordCode.split("-");
            sWordCode = sry[0];
            eWordCode = sry[1];
        }else if(BaseUtil.checkValueIsNull(wordCode).contains(",")){
            String[] sry = wordCode.split(",");
            wordCodeList.add(sry[0]);
            wordCodeList.add(sry[1]);
        }else {
            if(!BaseUtil.checkValueIsNull(wordCode).equals("")){
                wordCodeList.add(wordCode);
            }
        }
            return chronologicalAccountDao.selectChronologicalAccountByParam(
                    accsetsId,
                    sTime,
                    eTime,
                    sWordCode,
                    eWordCode,
                    word,
                    summary,
                    createMemberName ,
                    sSubjectCode,
                    eSubjectCode,
                    sMoney,
                    eMoney,
                    sort,
                    wordCodeList,
                    subCodeList
            );
    }

    @Override
    public List<ChronologicalAccountVo> selectChronologicalAccountByCurrencyParam(Integer accsetsId,
                                                                          String sTime,
                                                                          String eTime,
                                                                          String wordCode,
                                                                          String word,
                                                                          String summary,
                                                                          String createMemberName,
                                                                          String subjectCode,
                                                                          String sMoney,
                                                                          String eMoney,
                                                                          Integer sort,
                                                                          Integer currencyId
    ) {
        String sSubjectCode="";
        String eSubjectCode="";
        String sWordCode = "";
        String eWordCode = "";

        List<String> wordCodeList = new ArrayList<>();
        List<String> subCodeList = new ArrayList<>();

        // 对 科目进行 判断
        if(BaseUtil.checkValueIsNull(subjectCode).contains("-")){
            String[] sry = subjectCode.split("-");
            sSubjectCode = sry[0];
            eSubjectCode = sry[1];
        }else if(BaseUtil.checkValueIsNull(subjectCode).contains(",")){
            String[] sry = subjectCode.split(",");
            subCodeList.add(sry[0]);
            subCodeList.add(sry[1]);
        }else {
            if(!BaseUtil.checkValueIsNull(subjectCode).equals("")){
                subCodeList.add(subjectCode);
            }
        }

        //对 凭证字号 判断
        if(BaseUtil.checkValueIsNull(wordCode).contains("-")){
            String[] sry = wordCode.split("-");
            sWordCode = sry[0];
            eWordCode = sry[1];
        }else if(BaseUtil.checkValueIsNull(wordCode).contains(",")){
            String[] sry = wordCode.split(",");
            wordCodeList.add(sry[0]);
            wordCodeList.add(sry[1]);
        }else {
            if(!BaseUtil.checkValueIsNull(wordCode).equals("")){
                wordCodeList.add(wordCode);
            }
        }
        if (currencyId == -1){
            return chronologicalAccountDao.selectChronologicalAccountByParam(
                    accsetsId,
                    sTime,
                    eTime,
                    sWordCode,
                    eWordCode,
                    word,
                    summary,
                    createMemberName ,
                    sSubjectCode,
                    eSubjectCode,
                    sMoney,
                    eMoney,
                    sort,
                    wordCodeList,
                    subCodeList
            );
        }else if (currencyId == -2){

            return chronologicalAccountDao.selectChronologicalAccountByParamBaseCurrency

                    (
                            accsetsId,
                            sTime,
                            eTime,
                            sWordCode,
                            eWordCode,
                            word,
                            summary,
                            createMemberName ,
                            sSubjectCode,
                            eSubjectCode,
                            sMoney,
                            eMoney,
                            sort,
                            wordCodeList,
                            subCodeList
                    );
        }else {
            return chronologicalAccountDao.selectChronologicalAccountByCurrencyParam(
                    accsetsId,
                    sTime,
                    eTime,
                    sWordCode,
                    eWordCode,
                    word,
                    summary,
                    createMemberName ,
                    sSubjectCode,
                    eSubjectCode,
                    sMoney,
                    eMoney,
                    sort,
                    wordCodeList,
                    subCodeList,
                    currencyId
            );
        }

    }

    @Override
    public int updateQiChu(VoucherDetails voucherDetails) {
        return voucherDetailsMapper.updateQiChu(voucherDetails);
    }

    @Override
    public boolean removeAuxiliary(Integer subjectId,String name) {
        name = name.substring(name.indexOf("_"));
        List<VoucherDetails> detailsList = voucherDetailsMapper.countAuxiliary(subjectId,name);
        boolean flag =false;
        for (VoucherDetails voucherDetails : detailsList) {
            if(voucherDetails.getAuxiliaryTitle().contains(name)){
                flag = true;
                break;
            }
        }
        if(flag){
            return false;
        }
        int y = voucherDetailsMapper.removeAuxiliary(subjectId,name);
        if(y > 0){
            return true;
        }
        return false;
    }

    @Override
    public Boolean checkIsInsertQiChu(Integer accountSetsId, Integer subjectId, List<CategoryVo> categoryVoList) {
        List<Integer> count = voucherDetailsMapper.checkIsInsertQiChu(accountSetsId,subjectId,categoryVoList);
        if (count == null || count.size() == 0 || count.get(0)<categoryVoList.size() ){
            //说明该科目下没有该辅助的期初
            return true;
        }
        return false;
    }

    @Override
    public void delQIChu(Integer accountSetsId, Integer subjectId, String subjectCode) {
        voucherDetailsMapper.delQIChu(accountSetsId,subjectId,subjectCode);
    }
}











